package model;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;

import util.LoggingUtils;
import util.PlayerUtilities;

public class Playlist implements Comparable<Playlist> {
	private int						id;
	private String					name;
	private int						order;
	private boolean					active;

	private List<PlaylistRecord>	records;

	public Playlist(int id, String name, int order, boolean active) {
		this.id = id;
		this.name = name;
		this.order = order;
		this.active = active;
		this.records = new ArrayList<PlaylistRecord>();
	}

	@Override
	public int hashCode() {
		return this.id;
	}

	@Override
	public boolean equals(Object o) {
		if (o instanceof Playlist) {
			Playlist p = (Playlist) o;
			if (p.id == this.id) {
				return true;
			}
		}
		return false;
	}

	public static List<Playlist> getPlaylistFromCSVFile(String fileName) {
		List<Playlist> playlists = new ArrayList<Playlist>();
		if (!new File(fileName).exists()) {
			return playlists;
		}

		List<String[]> csvData = PlayerUtilities.getArrayFromCSVFile(fileName);
		String[] fields = csvData.remove(0);

		for (String[] playlistData : csvData) {
			int id = 0;
			String name = "";
			int order = 0;
			boolean active = true;
			boolean isValidPlaylist = false;

			// loop through each row and fetch Content data
			for (int i = 0; i < fields.length; i++) {
				String field = fields[i];
				try {
					if (field.equals("playlist_id")) {
						isValidPlaylist = true;
						id = Integer.parseInt(playlistData[i]);
					} else if (field.equals("playlist_name")) {
						name = playlistData[i];
					} else if (field.equals("playlist_order")) {
						order = Integer.parseInt(playlistData[i]);
					} else if (field.equals("playlist_active")) {
						active = playlistData[i].equals("1") ? true : false;
					} else {
						System.err.println("invalid content field: " + field);
					}
				} catch (NumberFormatException ex) {
					isValidPlaylist = false;
					System.out.println("invalid data format from source file.");
					ex.printStackTrace();
					
					String classMethod = "model.Playlist in getPlaylistFromCSVFile(String fileName)";
					LoggingUtils.logStart(classMethod);
					LoggingUtils.log(Level.SEVERE,ex.getMessage()+" invalid data format from source file."+classMethod,ex);
				}
				catch (ArrayIndexOutOfBoundsException ix)
				{
					String classMethod = "model.Playlist in getPlaylistFromCSVFile(String fileName)";
					LoggingUtils.logStart(classMethod);
					LoggingUtils.log(Level.SEVERE, ix.getMessage()+" Index out of bound exception "+classMethod,ix);					
				}
				catch(NullPointerException nu)
				{
					String classMethod = "model.Playlist in getPlaylistFromCSVFile(String fileName)";
					LoggingUtils.logStart(classMethod);
					LoggingUtils.log(Level.SEVERE, nu.getMessage()+" Null pointer exception "+classMethod,nu);
				}
			}
			if (isValidPlaylist) {
				Playlist p = new Playlist(id, name, order, active);
				playlists.add(p);
			}
		}
		return playlists;
	}

	/**
	 * @return the id
	 */
	public int getId() {
		return this.id;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return this.name;
	}

	/**
	 * @return the order
	 */
	public int getOrder() {
		return this.order;
	}

	/**
	 * @return the active
	 */
	public boolean isActive() {
		return this.active;
	}

	@Override
	public int compareTo(Playlist p) {
		if (p.getOrder() == this.getOrder()) {
			return this.id - p.getId();
		} else {
			return this.getOrder() - p.getOrder();
		}
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append(String.format("%s(%d) order: %d, total of %d playlist records", this.getName(), this.getId(),
				this.getOrder(), this.records.size()));
		// for (PlaylistRecord r : this.records) {
		// sb.append(r.toString()).append("\n");
		// }
		return sb.toString();
	}

	public boolean addRecord(PlaylistRecord r) {
		if (this.records.contains(r)) {
			this.records.remove(r);
		}
		this.records.add(r);
		return true;
	}

	public boolean removeRecord(int id) {
		PlaylistRecord delete = null;
		for (PlaylistRecord r : this.records) {
			if (r.getId() == id) {
				delete = r;
				break;
			}
		}

		if (delete == null) {
			return false;
		} else {
			delete.getContent().delete();
			return this.records.remove(delete);
		}
	}

	public boolean containsRecord(PlaylistRecord r) {
		return this.records.contains(r);
	}

	public void sortRecords() {
		Collections.sort(this.records);
	}

	public boolean play() {
		boolean playedAtLeastOneRecord = false;
		for (PlaylistRecord record : this.records) {
			boolean played = record.play();
			playedAtLeastOneRecord = played || playedAtLeastOneRecord;
		}
		return playedAtLeastOneRecord;
	}

	public List<PlaylistRecord> getRecords() {
		return this.records;
	}
}
